#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：MessageHandler.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/4/12 上午8:39 
"""

import json
import os
import socket
import threading
import time
from typing import Dict, List, Any

from dotenv import load_dotenv

from 配置文件 import ConfigManager
from 日志管理 import SingletonLogger


class MessageHandler:
	def __init__(self):
		"""
		初始化 MessageHandler 类，从环境变量中获取 JSON 配置文件路径，
		并加载配置文件、提取默认报文。
		"""
		load_dotenv()
		self.stop_loop = False
		self.config_file_path = os.environ.get("CONFIG_FILE_PATH")
		self.config_dict: Dict[str, Any] = self.load_json(self.config_file_path)
		self.default_message: str = self._get_default_message()

	@staticmethod
	def load_json(file_path: str) -> Dict[str, Any]:
		"""
		加载并解析指定路径的 JSON 配置文件为字典。
		:param file_path: JSON 配置文件路径
		:return: 解析后的字典
		"""
		# with open(file_path, "r", encoding="utf-8") as f:
		# 	return json.load(f)
		return ConfigManager.ConfigManager.load_config(file_path)

	def _get_default_message(self) -> str:
		"""
		从配置字典中获取默认报文。
		:return: 默认报文字符串
		"""
		default_message_key = "default_message"  # 调整此键名以匹配实际配置
		return self.config_dict.get(default_message_key, "")

	def loop_send_messages(self, interval: float = 5.0) -> None:
		"""
		循环发送报文到所有目标地址，每次循环间隔指定的时间。
		可通过设置`self.stop_loop`为`True`来停止循环。
		"""
		while not self.stop_loop:
			self.send_messages()
			time.sleep(interval)

	def send_messages(self) -> None:
		"""
		并发发送报文到所有目标地址。每个目标地址的发送任务在一个单独的线程中执行，
		以确保某个地址发送阻塞不会影响其他地址。
		"""
		targets: List[Dict[str, Any]] = self.config_dict.get("targets", [])

		if not targets:
			logging.info("目标地址列表为空，不执行发送操作。")
			return

		def send_to_target(target: Dict[str, Any]) -> None:
			"""
			连接到指定 IP 和端口，发送报文，并处理可能发生的异常。
			:param target: 包含 IP、端口及可选报文信息的目标字典
			"""
			ip: str = target["ip"]
			port: int = target["port"]
			message: str = target.get("message", self.default_message)

			with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
				try:
					s.connect((ip, port))
					s.sendall(message.encode())
					logging.info(f"已发送报文至 {ip}:{port}")
				except (socket.gaierror, ConnectionRefusedError) as e:
					logging.error(f"发送至 {ip}:{port} 失败：{e}")
			# Optional: Add retry logic here if needed.

		threads: List[threading.Thread] = []

		for target in targets:
			thread = threading.Thread(target=send_to_target, args=(target,))
			thread.start()
			threads.append(thread)

		for thread in threads:
			thread.join()


logging = SingletonLogger.SingletonLogger()
# 使用示例：
handler = MessageHandler()
handler.send_messages()
